﻿using UnityEngine;
using UnityEngine.EventSystems;

namespace BToolkit
{
    public class TouchRotateUIByTwoFingers : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
    {
        public BButton rotateBar;

        RectTransform rectTransform;
        float previousAngle;
        int fingerId1 = -1, fingerId2 = -1;
        bool isBarMode;
        float preAngle;
        Canvas _canvas;
        Canvas Canvas { get { return _canvas ?? (_canvas = GetComponentInParent<Canvas>()); } }

        private void OnDestroy()
        {
            if (rotateBar)
            {
                rotateBar.RemoveDown(onRotateBarForMouseTouchDown);
            }
        }

        void Awake()
        {
            rectTransform = transform as RectTransform;
            if (rotateBar)
            {
                rotateBar.AddDown(onRotateBarForMouseTouchDown);
            }
        }

        void onRotateBarForMouseTouchDown()
        {
            isBarMode = true;
            Vector2 touchPos = BUtils.ScreenToUGUIPoint(Input.mousePosition, Canvas);
            Vector2 centerPos = LocalToRootPos(rectTransform);
            float y = touchPos.y - centerPos.y;
            float x = touchPos.x - centerPos.x;
            preAngle = Mathf.Atan2(y, x) * Mathf.Rad2Deg;
        }

        void Update()
        {
            if (!Application.isEditor)
            {
                if (fingerId1 != -1 && fingerId2 != -1)
                {
                    Touch touch1 = new Touch(), touch2 = new Touch();
                    for (int i = 0; i < Input.touchCount; i++)
                    {
                        Touch touch = Input.GetTouch(i);
                        if (touch.fingerId == fingerId1)
                        {
                            touch1 = touch;
                        }
                        else if (touch.fingerId == fingerId2)
                        {
                            touch2 = touch;
                        }
                    }
                    TwoPointUpdate(touch1.position, touch2.position);
                }
            }
            if (rotateBar && isBarMode)
            {
                Vector2 touchPos = BUtils.ScreenToUGUIPoint(Input.mousePosition, Canvas);
                Vector2 centerPos = LocalToRootPos(rectTransform);
                float y = touchPos.y - centerPos.y;
                float x = touchPos.x - centerPos.x;
                float _angle = Mathf.Atan2(y, x) * Mathf.Rad2Deg;
                float _delta = _angle - preAngle;
                preAngle = _angle;
                transform.localEulerAngles += new Vector3(0, 0, _delta);
                if (Input.GetMouseButtonUp(0))
                {
                    isBarMode = false;
                }
            }
        }

        public virtual void OnPointerDown(PointerEventData eventData)
        {
            if (fingerId1 == -1)
            {
                fingerId1 = eventData.pointerId;
            }
            else if (fingerId2 == -1)
            {
                previousAngle = 0f;
                fingerId2 = eventData.pointerId;
            }
        }

        public virtual void OnPointerUp(PointerEventData eventData)
        {
            if (fingerId1 == eventData.pointerId)
            {
                fingerId1 = -1;
            }
            else if (fingerId2 == eventData.pointerId)
            {
                fingerId2 = -1;
            }
        }

        void TwoPointUpdate(Vector2 firstPos, Vector2 secondPos)
        {
            Vector2 uiPos1 = BUtils.ScreenToUGUIPoint(firstPos, Canvas);
            Vector2 uiPos2 = BUtils.ScreenToUGUIPoint(secondPos, Canvas);
            if (previousAngle == 0f)
            {
                previousAngle = Mathf.Atan2(uiPos2.y - uiPos1.y, uiPos2.x - uiPos1.x) * 180f / Mathf.PI;
            }
            else
            {
                float currAngle = Mathf.Atan2(uiPos2.y - uiPos1.y, uiPos2.x - uiPos1.x) * 180f / Mathf.PI;
                float deltaAngle = currAngle - previousAngle;
                previousAngle = currAngle;
                transform.localEulerAngles += new Vector3(0, 0, deltaAngle);
            }
        }

        Vector2 LocalToRootPos(RectTransform target)
        {
            Vector2 pos = target.anchoredPosition;
            while (!target.parent.GetComponent<Canvas>())
            {
                target = target.parent as RectTransform;
                pos += new Vector2(target.anchoredPosition.x * target.localScale.x, target.anchoredPosition.y * target.localScale.y);
            }
            return pos;
        }
    }
}